#!C:\Users\Hasee\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.9
import sys, requests, time
#encoding=utf-8
import json
import time
import logging
from aliyunsdkcore.acs_exception.exceptions import ServerException, ClientException
from aliyunsdkcore.request import RoaRequest
from aliyunsdkcore.client import AcsClient
from aliyunsdkvpc.request.v20160428 import CreateVpcRequest
from aliyunsdkvpc.request.v20160428 import CreateVSwitchRequest
from aliyunsdkvpc.request.v20160428 import DeleteVSwitchRequest
from aliyunsdkvpc.request.v20160428 import DeleteVpcRequest
from aliyunsdkvpc.request.v20160428 import DescribeVSwitchAttributesRequest
from aliyunsdkvpc.request.v20160428 import DescribeVpcAttributeRequest
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
from aliyunsdkecs.request.v20140526.RunInstancesRequest import RunInstancesRequest
from aliyunsdkecs.request.v20140526.CreateSecurityGroupRequest import CreateSecurityGroupRequest
from aliyunsdkecs.request.v20140526 import DescribeSecurityGroupAttributeRequest
from aliyunsdkecs.request.v20140526 import DescribeSecurityGroupsRequest
from aliyunsdkecs.request.v20140526 import RevokeSecurityGroupRequest
from aliyunsdkecs.request.v20140526 import AuthorizeSecurityGroupRequest
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')


#设置可用区
zone_id = "cn-beijing-h"

# 设置实例规格。
# instance_type = "指定规格(例如ecs.s6-c1m1.small)"
instance_type = "ecs.s6-c1m1.small"

# 使用的镜像信息。
# image_id = "指定镜像(例如centos_stream_8_x64_20G_alibase_20211115.vhd)"
image_id = "centos_stream_8_x64_20G_alibase_20211115.vhd"

# 当前VPC类型的安全组。
# security_group_id = "指定安全组(例如sg-2ze75**********)"

#公网IP地址
ip_address = []

#设置实例密码
instance_password='123456'

#网络计费
internet_charge_type = "PayByTraffic"

# 批量创建ECS实例的数量, 取值范围：1-100, 默认值：1
amount = 1

# 自动释放时间。使用UTC时间，格式为 yyyy-MM-ddTHH:mm:ssZ。最短释放时间为当前时间半小时之后；最长释放时间不能超过当前时间三年
auto_release_time = "2021-12-14T08:30:00Z"

class VpcQuickStart(object):
    def __init__(self, client):
        self.client = client
        self.TIME_DEFAULT_OUT = 15
        self.DEFAULT_TIME = 1

    def check_status(self,time_default_out, default_time, func, check_status, id):
        for i in range(time_default_out):
            time.sleep(default_time)
            status = func(id)
            if status == check_status:
                return True
        return False

    def create_vpc(self):
        try:
            request = CreateVpcRequest.CreateVpcRequest()
            request.set_CidrBlock("192.168.0.0/20")
            response = self.client.do_action_with_exception(request)
            response_json = json.loads(response)
            # 判断VPC状态是否可用
            if self.check_status(self.TIME_DEFAULT_OUT, self.DEFAULT_TIME,
                                        self.describe_vpc_status,
                                        "Available", response_json['VpcId']):
                return response_json
        except ServerException as e:
            print(e)
        except ClientException as e:
            print(e)

    def delete_vpc(self, params):
        try:
            request = DeleteVpcRequest.DeleteVpcRequest()
            # 要删除的VPC的ID
            request.set_VpcId(params['vpc_id'])
            response = self.client.do_action_with_exception(request)
            response_json = json.loads(response)
            return response_json
        except ServerException as e:
            print(e)
        except ClientException as e:
            print(e)

    def describe_vpc_attribute(self, vpc_id):
        try:
            request = DescribeVpcAttributeRequest.DescribeVpcAttributeRequest()
            # 要查询的VPC的ID
            request.set_VpcId(vpc_id)
            response = self.client.do_action_with_exception(request)
            response_json = json.loads(response)
            return response_json
        except ServerException as e:
            print(e)
        except ClientException as e:
            print(e)

    def describe_vpc_status(self, vpc_id):
        response = self.describe_vpc_attribute(vpc_id)
        return response["Status"]

    def create_vswitch(self, params):
        try:
            request = CreateVSwitchRequest.CreateVSwitchRequest()
            # 交换机所属区的ID，您可以通过调用DescribeZones接口获取地域ID
            request.set_ZoneId(params['zone_id'])
            # 交换机所属的VPC的ID
            request.set_VpcId(params['vpc_id'])
            # 交换机的网段
            request.set_CidrBlock(params['cidr_block'])
            response = self.client.do_action_with_exception(request)
            response_json = json.loads(response)
            # 判断交换机状态是否可用
            if self.check_status(self.TIME_DEFAULT_OUT, self.DEFAULT_TIME,
                                        self.describe_vswitch_status,
                                        "Available", response_json['VSwitchId']):
                return response_json
        except ServerException as e:
            print(e)
        except ClientException as e:
            print(e)

    def describe_vswitch_attribute(self, vswitch_id):
        try:
            request = DescribeVSwitchAttributesRequest.DescribeVSwitchAttributesRequest()
            request.set_VSwitchId(vswitch_id)
            response = self.client.do_action_with_exception(request)
            response_json = json.loads(response)
            return response_json
        except ServerException as e:
            print(e)
        except ClientException as e:
            print(e)

    def describe_vswitch_status(self, vswitch_id):
        response = self.describe_vswitch_attribute(vswitch_id)
        return response["Status"]

    def delete_vswitch(self, params):
        try:
            request = DeleteVSwitchRequest.DeleteVSwitchRequest()
            # 要删除的交换机的ID
            request.set_VSwitchId(params['vswitch_id'])
            response = self.client.do_action_with_exception(request)
            response_json = json.loads(response)
            # 判断交换机是否被删除成功
            if self.check_status(self.TIME_DEFAULT_OUT, self.DEFAULT_TIME * 5,
                                        self.describe_vswitch_status,
                                        '', params['vswitch_id']):
                return response_json
        except ServerException as e:
            print(e)
        except ClientException as e:
            print(e)

# 查询安全组规则
def describeSecurityGroupAttributeRequest():
    request = DescribeSecurityGroupAttributeRequest.DescribeSecurityGroupAttributeRequest()
    request.set_SecurityGroupId('sg-9xxxx')
    request.set_accept_format('json')
    return request

# 查询安全组名称
def describeSecurityGroupsRequest():
    request = DescribeSecurityGroupsRequest.DescribeSecurityGroupsRequest()
    request.set_accept_format('json')
    return request

#撤销安全组规则
def revokeSecurityGroupRequest():
    request = RevokeSecurityGroupRequest.RevokeSecurityGroupRequest()
    request.set_SecurityGroupId('sg-9xxxx')
    request.set_IpProtocol('all')
    request.set_PortRange('-1/-1')
    request.set_SourceCidrIp('0.0.0.0/0')
    request.set_Policy('accept')
    request.set_accept_format('json')
    return request

#授权安全组规则
def authorizeSecurityGroupRequest(security_group_id,protocol,port):
    request = AuthorizeSecurityGroupRequest.AuthorizeSecurityGroupRequest()
    request.set_SecurityGroupId(security_group_id)
    request.set_IpProtocol(protocol)
    request.set_PortRange(str(port)+'/'+str(port))
    request.set_SourceCidrIp('0.0.0.0/0')
    request.set_Priority('100')
    request.set_Policy('accept')
    request.set_accept_format('json')
    return request

# 创建ECS实例并启动
def create_multiple_instances():
    request = build_request()
    request.set_Amount(amount)
    _execute_request(request)

# 创建ECS实例并分配公网IP
def create_multiple_instances_with_public_ip():
    request = build_request()
    request.set_Amount(amount)
    request.set_InternetMaxBandwidthOut(5)
    _execute_request(request)

# 创建ECS实例并设置自动释放时间
def create_multiple_instances_with_auto_release_time():
    request = build_request()
    request.set_Amount(amount)
    request.set_AutoReleaseTime(auto_release_time)
    _execute_request(request)

#综合批量创建ECS实例
def create_multiple_instances_with_public_ip_and_auto_release_time(instance_hostname,vswitch_id,security_group_id):
    request = build_request(instance_hostname,vswitch_id,security_group_id)
    request.set_Amount(amount)
    request.set_InternetMaxBandwidthOut(5)
    request.set_AutoReleaseTime(auto_release_time)
    _execute_request(request)

def _execute_request(request):
    response = _send_request(request)
    if response.get('Code') is None:
        instance_ids = response.get('InstanceIdSets').get('InstanceIdSet')
        running_amount = 0
        while running_amount < amount:
            time.sleep(10)
            running_amount = check_instance_running(instance_ids)
    print("ecs instance {0} is running".format(instance_ids))

def check_instance_running(instance_ids):
    request = DescribeInstancesRequest()
    request.set_InstanceIds(json.dumps(instance_ids))
    response = _send_request(request)
    if response.get('Code') is None:
        instances_list = response.get('Instances').get('Instance')
        running_count = 0
        for instance_detail in instances_list:
            if instance_detail.get('Status') == "Running":
                running_count += 1
                ip_address.append(instance_detail.get('PublicIpAddress').get('IpAddress')[0])
    # print('公网ip为'+ip_address[0])
    return running_count

def build_request(instance_hostname,vswitch_id,security_group_id):
    request = RunInstancesRequest()
    request.set_ZoneId(zone_id)
    request.set_ImageId(image_id)
    request.set_VSwitchId(vswitch_id)
    request.set_SecurityGroupId(security_group_id)
    # request.set_InstanceName(instance_name)
    request.set_InstanceType(instance_type)
    # 指定盘类型和系统盘大小，其实不写也行，这些都是默认
    request.set_SystemDiskCategory("cloud_essd")    #系统盘类型
    request.set_SystemDiskSize("40")    #系统盘大小
    # 主机名也可以不指定，创建之后手动改
    request.set_HostName(instance_hostname)
    # 不指定密码的话可以去控制台自己修改，总感觉把密码设在这里不是很安全
    request.set_Password(instance_password)
    # 以下可不加，默认就是按量付费，按照你释放的时间取小时计费，所以其实只需设置释放时间即可    
    request.set_InstanceChargeType("PostPaid")   #设置按量付费
    request.set_Period(1)    #购买时长
    request.set_PeriodUnit("Hourly")    #购买资源的时长单位
    request.set_InternetChargeType("PayByTraffic")
    request.set_IoOptimized("optimized")
    request.set_SecurityEnhancementStrategy("Active")
    request.set_SystemDiskPerformanceLevel("PL0")
    return request

# 发送API请求
def _send_request(request):
    request.set_accept_format('json')
    try:
        response_str = client.do_action(request)
        logging.info(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        logging.error(e)

def create_security_group(client,vpc_id):
    request = CreateSecurityGroupRequest()
    request.set_SecurityGroupType('normal')
    request.set_VpcId(vpc_id)
    request.set_accept_format('json')
    response = client.do_action_with_exception(request)
    response_json = json.loads(response)
    return response_json

if __name__ == "__main__":
    AccessId ='' #阿里云获取
    AccessSecret =''  #阿里云获取
    client = AcsClient(AccessId,AccessSecret,'cn-beijing',timeout = 35)
    vpc_quick_start = VpcQuickStart(client)
    params = {}
    params['zone_id'] = "cn-beijing-h"
    params['cidr_block'] = "192.168.0.0/24"

    # 创建vpc
    vpc_json = vpc_quick_start.create_vpc()
    print("---------------------------create_vpc---------------------------")
    print(vpc_json)
    vpc_id = vpc_json['VpcId']

    # 创建vSwitch
    params['vpc_id'] = vpc_json['VpcId']
    vswitch_json = vpc_quick_start.create_vswitch(params)
    print("---------------------------create_vswitch---------------------------")
    print(vswitch_json)
    vswitch_id = vswitch_json['VSwitchId']

    #创建安全组
    security_json = create_security_group(client,vpc_id)
    security_group_id = security_json['SecurityGroupId']

    #安全组默认添加基本规则
    client.do_action(authorizeSecurityGroupRequest(security_group_id,'tcp',80))
    client.do_action(authorizeSecurityGroupRequest(security_group_id,'tcp',443))
    client.do_action(authorizeSecurityGroupRequest(security_group_id,'tcp',22))
    client.do_action(authorizeSecurityGroupRequest(security_group_id,'tcp',3389))
    client.do_action(authorizeSecurityGroupRequest(security_group_id,'icmp',-1))

    #创建ECS
    print ("hello ecs batch create instance")
    instance_hostname = input('请指定主机名:')
    create_multiple_instances_with_public_ip_and_auto_release_time(instance_hostname, vswitch_id, security_group_id)
    print('初始root密码为:'+instance_password)
    print('公网ip为'+ip_address[0])

#------------------------------------------------------------------------------------------------------------------------------------------

#jumpserver脚本的操作函数
 
#用户操作
class HTTP:
    server = None
    token  = None
@classmethod
#获取token
def get_token(cls, username, password):
    data              = {'username': username, 'password': password}
    url               = "/api/v1/authentication/auth/"
    res               = requests.post(cls.server + url, data)
    res_data          = res.json()
    if res.status_code in [200, 201] and res_data:
        token         = res_data.get('token')
        cls.token     = token
    else:
        print("获取 token 错误, 请检查输入项是否正确")
        sys.exit()

@classmethod
def get(cls, url, params=None, **kwargs):
    url               = cls.server + url
    headers           = {
        'Authorization': "Bearer {}".format(cls.token),
        'X-JMS-ORG': '00000000-0000-0000-0000-000000000002'
    }
    kwargs['headers'] = headers
    res               = requests.get(url, params, **kwargs)
    return res

@classmethod
def post(cls, url, data=None, json=None, **kwargs):
    url               = cls.server + url
    headers           = {
        'Authorization': "Bearer {}".format(cls.token),
        'X-JMS-ORG': '00000000-0000-0000-0000-000000000002'
    }
    kwargs['headers'] = headers
    res               = requests.post(url, data, json, **kwargs)
    return res
class User(object):

    def __init__(self):
        self.id           = None
        self.name         = user_name
        self.username     = user_username
        self.email        = user_email

    def exist(self):
        url               = '/api/v1/users/users/'
        params            = {'username': self.username}
        res               = HTTP.get(url, params=params)
        res_data          = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id       = res_data[0].get('id')
        else:
            self.create()

    def create(self):
        print("创建用户 {}".format(self.username))
        url               = '/api/v1/users/users/'
        data              = {
            'name': self.name,
            'username': self.username,
            'email': self.email,
            'is_active': True
        }
        res               = HTTP.post(url, json=data)
        self.id           = res.json().get('id')
        

    def perform(self):
        self.exist()
#资源节点
class Node(object):

    def __init__(self):
        self.id           = None
        self.name         = asset_node_name

    def exist(self):
        url               = '/api/v1/assets/nodes/'
        params            = {'value': self.name}
        res               = HTTP.get(url, params=params)
        res_data          = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id       = res_data[0].get('id')
        else:
            self.create()

    def create(self):
        print("创建资产节点 {}".format(self.name))
        url               = '/api/v1/assets/nodes/'
        data              = {
            'value': self.name
        }
        res               = HTTP.post(url, json=data)
        self.id           = res.json().get('id')

    def perform(self):
        self.exist()
#管理用户
class AdminUser(object):

    def __init__(self):
        self.id           = None
        self.name         = assets_admin_name
        self.username     = assets_admin_username
        self.password     = assets_admin_password

    def exist(self):
        url               = '/api/v1/assets/admin-user/'
        params            = {'username': self.name}
        res               = HTTP.get(url, params=params)
        res_data          = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id       = res_data[0].get('id')
        else:
            self.create()

    def create(self):
        print("创建管理用户 {}".format(self.name))
        url               = '/api/v1/assets/admin-users/'
        data              = {
            'name': self.name,
            'username': self.username,
            'password': self.password
        }
        res               = HTTP.post(url, json=data)
        self.id           = res.json().get('id')

    def perform(self):
        self.exist()

class Asset(object):

    def __init__(self):
        self.id           = None
        self.name         = asset_name
        self.ip           = asset_ip
        self.platform     = asset_platform
        self.protocols    = asset_protocols
        self.admin_user   = AdminUser()
        self.node         = Node()

    def exist(self):
        url               = '/api/v1/assets/assets/'
        params            = {
            'hostname': self.name
        }
        res               = HTTP.get(url, params)
        res_data          = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id       = res_data[0].get('id')
            ASSETid=self.id
        else:
            self.create()

    def create(self):
        print("创建资产 {}".format(self.ip))
        self.admin_user.perform()
        self.node.perform()
        url               = '/api/v1/assets/assets/'
        data              = {
            'hostname': self.ip,
            'ip': self.ip,
            'platform': self.platform,
            'protocols': self.protocols,
            'admin_user': self.admin_user.id,
            'nodes': [self.node.id],
            'is_active': True
        }
        res               = HTTP.post(url, json=data)
        self.id           = res.json().get('id')

    def perform(self):
        self.exist()

class SystemUser(object):

    def __init__(self):
        self.id           = None
        self.name         = assets_system_name
        self.username     = assets_system_username

    def exist(self):
        url               = '/api/v1/assets/system-users/'
        params            = {'name': self.name}
        res               = HTTP.get(url, params)
        res_data          = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id       = res_data[0].get('id')
        else:
            self.create()

    def create(self):
        print("创建系统用户 {}".format(self.name))
        url               = '/api/v1/assets/system-users/'
        data              = {
            'name': self.name,
            'username': self.username,
            'login_mode': 'auto',
            'protocol': 'ssh',
            'auto_push': True,
            'sudo': 'All',
            'shell': '/bin/bash',
            'auto_generate_key': True,
            'is_active': True
        }
        res               = HTTP.post(url, json=data)
        self.id           = res.json().get('id')
        print('------------',self.id)
        #  #二次推送用户
        url2               = '/api/v1/assets/system-users/'+self.id+'/tasks/'
        data2              = {
            'action': "push",
            'asset': ASSETid,
            'assets': [ASSETid]
        }
        re                  =HTTP.post(url2, json=data2)
       # time.sleep(7)
        re_data             = re.json()
        

    def perform(self):
        self.exist()
        

class AssetPermission(object):

    def __init__(self):
        self.name         = perm_name
        self.user         = User()
        self.asset        = Asset()
        self.system_user  = SystemUser()

    def create(self):
        print("创建资产授权名称 {}".format(self.name))
        url               = '/api/v1/perms/asset-permissions/'
        data              = {
            'name': self.name,
            'users': [self.user.id],
            'assets': [self.asset.id],
            'system_users': [self.system_user.id],
            'actions': ['all'],
            'is_active': True,
            'date_start': perm_date_start,
            'date_expired': perm_date_expired
        }
        res               = HTTP.post(url, json=data)
        res_data          = res.json()
        if res.status_code in [200, 201] and res_data:
            print("创建资产授权规则成功: ", res_data)
        else:
            print("创建授权规则失败: ", res_data)
    def perform(self):
        self.user.perform()
        self.asset.perform()
        self.system_user.perform()
        self.create()
class AssetPermission2(object):#冗余匹配过程，提高稳定性

    def __init__(self):
        self.name         = perm_name
        self.user         = User()
        self.asset        = Asset()
        self.system_user  = SystemUser()
    def perform(self):
        self.user.perform()
        self.asset.perform()
        self.system_user.perform()

class APICreateAssetPermission(object):

    def __init__(self):
        self.jms_url      = jms_url
        self.username     = jms_username
        self.password     = jms_password
        self.token        = None
        self.server       = None

    def init_http(self):
        HTTP.server       = self.jms_url
        HTTP.get_token(self.username, self.password)

    def perform(self):
        self.init_http()
        self.perm         = AssetPermission()
        self.perm.perform()

class APICreateAssetPermission2(object):#再次推送以及创建用户，冗余增加稳定性

    def __init__(self):
        self.jms_url      = jms_url
        self.username     = jms_username
        self.password     = jms_password
        self.token        = None
        self.server       = None

    def init_http(self):
        HTTP.server       = self.jms_url
        HTTP.get_token(self.username, self.password)

    def perform(self):
        self.init_http()
        self.perm         = AssetPermission2()
        self.perm.perform()
if __name__ == '__main__':



    
    ASSETid=None
    # jumpserver url 地址
    jms_url                = 'http://192.168.1.108'

    # 管理员账户
    jms_username           = ''
    jms_password           = ''

    # 资产节点
    asset_node_name        = 'test'

    # 资产信息
    asset_name             = ''#ip_address[0]
    asset_ip               = ''#ip_address[0]
    asset_platform         = 'Linux'
    asset_protocols        = ['ssh/22']

    # 资产管理用户
    assets_admin_name      = 'root'+ ''#ip_address[0]
    assets_admin_username  = 'root'
    assets_admin_password  = '' #自己设置

    # 资产系统用户
    assets_system_name     = 'test18'
    assets_system_username = 'test18'

    # 用户用户名
    user_name              = '测试用户1'
    user_username          = 'test1'
    user_email             = '' 

    # 资产授权
    perm_name              = 'AutoPerm' +'_'+ (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    perm_date_start        = '2021-05-01 14:25:47 +0800'  #自己设置
    perm_date_expired      = '2022-06-01 14:25:47 +0800'

    api = APICreateAssetPermission()
    api.perform()
    api = APICreateAssetPermission2()
    api.perform()